﻿using System;
using System.Collections.Generic;
using OpenTK.Graphics.OpenGL4;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;

namespace Painter3D.RenderSys
{
    /// <summary>
    /// 材质对象
    /// <para>Texture0 用于默认贴图，工作使用材质从Texture1开始</para>
    /// </summary>
    public class Texture2D
    {
        readonly private int Handle;

        /// <summary>
        /// 创建纹理材质 [png rgba]
        /// </summary>
        /// <param name="path">图像文件路径</param>
        /*
        public Texture2D(string path)
        {
            using (Bitmap bmp = new Bitmap(path))
            {
                bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
                Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
                BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);

                IntPtr ptr = bmpData.Scan0;
                int bytes = bmpData.Stride * bmp.Height;
                byte[] texture = new byte[bytes];
                Marshal.Copy(ptr, texture, 0, bytes);
                bmp.UnlockBits(bmpData);

                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);

                Handle = GL.GenTexture();
                GL.ActiveTexture(TextureUnit.Texture0);
                GL.BindTexture(TextureTarget.Texture2D, Handle);
                GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp.Width, bmp.Height, 0, OpenTK.Graphics.OpenGL4.PixelFormat.Bgra, PixelType.UnsignedByte, texture);
                //GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Alpha, bmp.Width, bmp.Height, 0, OpenTK.Graphics.OpenGL4.PixelFormat.Alpha, PixelType.UnsignedByte, data);
                GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
            }
        }
        */

        /// <summary>
        /// 创建纹理材质 [rgba]
        /// </summary>
        /// <param name="path">图像文件路径</param>
        /// <param name="flipVertical">垂直反转图片</param>
        /// <param name="flipHorizontal">水平反转图片</param>
        public Texture2D(string path, bool flipVertical = true, bool flipHorizontal = false)
        {
            using (Image<Rgba32> image = Image.Load<Rgba32>(path))
            {
                if (flipHorizontal)
                    image.Mutate(x => x.Flip(FlipMode.Horizontal));
                if (flipVertical)
                    image.Mutate(x => x.Flip(FlipMode.Vertical));

                var pixels = new List<byte>(4 * image.Width * image.Height);
                for (int y = 0; y < image.Height; y++)
                {
                    var row = image.GetPixelRowSpan(y);
                    for (int x = 0; x < image.Width; x++)
                    {
                        pixels.Add(row[x].R);
                        pixels.Add(row[x].G);
                        pixels.Add(row[x].B);
                        pixels.Add(row[x].A);
                    }
                }

                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);

                Handle = GL.GenTexture();
                GL.ActiveTexture(TextureUnit.Texture0);
                GL.BindTexture(TextureTarget.Texture2D, Handle);
                GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixels.ToArray());
                GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
            }
        }

        /// <summary>
        /// 创建纹理材质
        /// </summary>
        /// <param name="width">宽</param>
        /// <param name="height">高</param>
        /// <param name="pixels">图像数据,字节数组</param>
        public Texture2D(int width, int height,byte[] pixels)
        {
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);

            Handle = GL.GenTexture();
            GL.ActiveTexture(TextureUnit.Texture0);
            GL.BindTexture(TextureTarget.Texture2D, Handle);
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width,height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixels);
            GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
        }

        /// <summary>
        /// 将对应材质绑定到纹理单元
        /// </summary>
        /// <param name="textureUnit">纹理单元</param>
        public void Use(int textureUnit = 0)
        {
            GL.ActiveTexture(TextureUnit.Texture0 + textureUnit);
            GL.BindTexture(TextureTarget.Texture2D, Handle);
        }

        public IntPtr Id()
        {
            return (IntPtr)Handle;
        }
    }
}
